﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using EyesOfTheDragon.Events;
using Microsoft.Xna.Framework.Graphics;
using XRpgLibrary.SpriteClasses;
using Anthem.Components;
using XRpgLibrary.Events;
using EyesOfTheDragon.Globals;

namespace EyesOfTheDragon.Components
{
    public class MonsterGenerator:IUpdate, IPauseable
    {
        public const string Monster_Killed = "Monster_Killed";
        public const string Boss_Killed = "Boss_Killed";
        public const string Map_Changing = "Map_Changing";
        private bool _enabled = false;
        private Random _random;
      //  private const int SpawnTriggerGID = 201;
        private const string triggerLayer = "triggersLayer";
        public bool Enabled
        {
            get { return _enabled; }
            set { _enabled = value; }
        }
        private float frequency = 5;
        private float elapsed = 3;
        private Dictionary<int, Area> Areas = new Dictionary<int, Area>();
        public class Area
        {
            public Area(float FREQUENCY, float NUM_REQUIRED)
            {
                numRequired = NUM_REQUIRED;
                frequency = FREQUENCY;
            }
            public float frequency = 5;
            public float numKilled = 0;
            public float numRequired = 5;
            public float numCreated = 0;
            public bool GeneratesMonsters = true;
            public bool containsBoss = false;
            public bool bossKilled = false;
            public bool bossCreated = false;
        }
        public void MonsterKilled()
        {
            Area curr = Areas[map.Instance.CurrentMap];
            curr.numKilled++;
            if (curr.numRequired <= curr.numKilled && Player.Instance.PlayerLevel < map.Instance.CurrentMap)
            {
                
                Player.Instance.PlayerLevel = map.Instance.CurrentMap;
            }
        }
        public void bossKilled()
        {
            Area curr = Areas[map.Instance.CurrentMap];
            curr.bossKilled = true;
        }
        public void MapChanging()
        {
            Areas[map.Instance.CurrentMap].bossCreated = false;
            Areas[map.Instance.CurrentMap].bossKilled = false;
            Areas[map.Instance.CurrentMap].numKilled = 0;
            Areas[map.Instance.CurrentMap].numCreated = 0;
        }
        public int MonstersRemaining
        {
            get 
            {
                Area curr = Areas[map.Instance.CurrentMap];
                int num = (int)(curr.numRequired - curr.numKilled);
                    if (num < 0)
                        return 0;
                return num;
                //return curr.numRequired - curr.numKilled;

            }
        }
        public void PlayerKilled()
        {
            for(int i = 1; i <= Areas.Count;i++)
            {
                Areas[i].numKilled = 0;
                Areas[i].bossKilled = false;
                Areas[i].bossCreated = false;
                Areas[i].numCreated = 0;
            }
        }
        public static MonsterGenerator Instance
        {
            get 
            {
                if (_instnace == null)
                    _instnace = new MonsterGenerator();
                return _instnace; 
            }

        }
        private Game _gameRef;
        bool initilized = false;
        public void init(Game GameRef)
        {
            if (initilized)
                return;
            _gameRef = GameRef;
            _enabled = true;
            UpdateList.Instance.add(this);
            _random = new Random();
            Area a1 = new Area(5, 1000);
            a1.GeneratesMonsters = false;
            Area a2 = new Area(2, 50);
            a2.containsBoss = false;
            //a2.containsBoss = false;
            Area a3 = new Area(1.5f, 30); 
            Area a4 = new Area(.8f, 50);
            a4.containsBoss = true;
            Areas.Add(1, a1);
            Areas.Add(2, a2);
            Areas.Add(3, a3);
            Areas.Add(4, a4);
            EventRouter.Instance.add(Monster_Killed, MonsterKilled);
            EventRouter.Instance.add(Player.PlayerKilled, PlayerKilled);
            EventRouter.Instance.add(Boss_Killed, bossKilled);
            EventRouter.Instance.add(Map_Changing, MapChanging);
            initilized = true;
        }
        public void Update(GameTime gt)
        {
            float seconds = gt.ElapsedGameTime.Milliseconds / 1000f;
            elapsed += seconds;
            Area curr = Areas[map.Instance.CurrentMap];
            if (elapsed > curr.frequency && curr.GeneratesMonsters)
            {
                List<GTile> tiles = map.Instance.getLayer(triggerLayer).getTiles(MapVariables.SpawnGID);
                if (tiles.Count > 0)
                {
                    elapsed = 0;
                    if (Areas[map.Instance.CurrentMap].numRequired <= Areas[map.Instance.CurrentMap].numKilled)
                    {
                        if (curr.containsBoss == true && !curr.bossCreated)
                        {
                            createMonster3();
                            curr.bossCreated = true;
                            curr.numCreated++;
                            return;
                        }
                        else
                            return;
                    }

                    if (map.Instance.CurrentMap == 1 || map.Instance.CurrentMap == 2)
                        createMonster();
                    else if (map.Instance.CurrentMap == 3)
                    {
                        createMonster2();
                    }
                    else
                    {
                        int rand = _random.Next(0,100);
                        if (rand > 50)
                            createMonster();
                        else
                            createMonster2();
                    }
                    curr.numCreated++;
                }
            }
        }
        private void createMonster()
        {
            AnimatedSprite sprite1;
            Texture2D spriteSheet2 = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\ballerina_walking");
            Texture2D monsterAttack = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\ballerina_attack");
            Dictionary<AnimationKey, Animation> animations1 = new Dictionary<AnimationKey, Animation>();
            Animation animation = new Animation(4, 64, 128, 0, 128);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Down, animation);
            animation = new Animation(4, 64, 128, 0, 128);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Left, animation);
            animation = new Animation(4, 64, 128, 0, 256);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Right, animation);
            animation = new Animation(3, 32, 128, 0, 256);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Up, animation);

            animation = new Animation(4, 125, 125, 0, 125);
            animation.Texture = monsterAttack;
            animations1.Add(AnimationKey.AttackLeft, animation);

            animation = new Animation(4, 125, 125, 0, 250);
            animation.Texture = monsterAttack;
            animations1.Add(AnimationKey.AttackRight, animation);

            sprite1 = new AnimatedSprite(spriteSheet2, animations1);
            BaseMonster bm = new BaseMonster(sprite1);
            bm.init();
            List<GTile> tiles = map.Instance.getLayer(triggerLayer).getTiles(MapVariables.SpawnGID);
            int ran = _random.Next(0, tiles.Count - 1);
            sprite1.Position = new Vector2(tiles[ran].Position.X, tiles[ran].Position.Y) ;
            bm.OurMonsterType = PauseManager.PauseType.Ballerina;
            //sprite1.Position = new Vector2(_random.Next(0,1000), _random.Next(0,1000));
            Monster.Instance.Monsters.Add(bm);
        }
        private void createMonster2()
        {
            AnimatedSprite sprite1;
            Texture2D spriteSheet2 = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\child_Running");
            Texture2D monsterAttack = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\Child_attack");
            Dictionary<AnimationKey, Animation> animations1 = new Dictionary<AnimationKey, Animation>();
            Animation animation = new Animation(4, 53, 106, 0, 106);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Down, animation);
            animation = new Animation(4, 53, 106, 0, 106);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Left, animation);
            animation = new Animation(4, 53, 106, 0, 212);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Right, animation);
            animation = new Animation(3, 53, 106, 0, 212);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Up, animation);

            animation = new Animation(4, 53, 106, 0, 106);
            animation.Texture = monsterAttack;
            animations1.Add(AnimationKey.AttackLeft, animation);

            animation = new Animation(4, 53, 106, 0, 212);
            animation.Texture = monsterAttack;
            animations1.Add(AnimationKey.AttackRight, animation);


            sprite1 = new AnimatedSprite(spriteSheet2, animations1);
            BaseMonster bm = new BaseMonster(sprite1);
            bm.init();
            List<GTile> tiles = map.Instance.getLayer(triggerLayer).getTiles(MapVariables.SpawnGID);
            if (tiles.Count > 0)
            {
                int ran = _random.Next(0, tiles.Count - 1);
                sprite1.Position = new Vector2(tiles[ran].Position.X, tiles[ran].Position.Y);
            }
            bm.OurMonsterType = PauseManager.PauseType.Child;
            //sprite1.Position = new Vector2(_random.Next(0,1000), _random.Next(0,1000));
            Monster.Instance.Monsters.Add(bm);
        }

        private void createMonster3()
        {
            AnimatedSprite sprite1;
            Texture2D spriteSheet2 = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\Boss_standing_still");
            Texture2D monsterAttack = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\Boss_attack01");
            Texture2D stunTexture = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\Boss_stunned");
            Texture2D damageTexture = _gameRef.Content.Load<Texture2D>(@"MonsterSprites\Boss_damage");


            Dictionary<AnimationKey, Animation> animations1 = new Dictionary<AnimationKey, Animation>();
            Animation animation = new Animation(4, 128, 128, 0, 128);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Left, animation);

            animation = new Animation(4, 128, 128, 0, 256);
            animation.Texture = spriteSheet2;
            animations1.Add(AnimationKey.Right, animation);

            animation = new Animation(4, 128, 128, 0, 128);
            animation.Texture = monsterAttack;
            animation.Loops = false;
            animations1.Add(AnimationKey.AttackLeft, animation);

            animation = new Animation(4, 128, 128, 0, 256);
            animation.Texture = monsterAttack;
            animation.Loops = false;
            animations1.Add(AnimationKey.AttackRight, animation);

            animation = new Animation(4, 128, 128, 0, 128);
            animation.Texture = stunTexture;
            animations1.Add(AnimationKey.StunLeft, animation);

            animation = new Animation(4, 128, 128, 0, 256);
            animation.Texture = stunTexture;
            animations1.Add(AnimationKey.StunRight, animation);

            animation = new Animation(4, 128, 128, 0, 128);
            animation.Texture = damageTexture;
            animations1.Add(AnimationKey.DamageLeft, animation);

            animation = new Animation(4, 128, 128, 0, 256);
            animation.Texture = damageTexture;
            animations1.Add(AnimationKey.DamageRight, animation);

            sprite1 = new AnimatedSprite(spriteSheet2, animations1);
            FinalBoss bm = new FinalBoss(sprite1);
            bm.init();
            List<GTile> tiles = map.Instance.getLayer(triggerLayer).getTiles(MapVariables.SpawnGID);
            int ran = _random.Next(0, tiles.Count - 1);
            sprite1.Position = new Vector2(tiles[ran].Position.X, tiles[ran].Position.Y - sprite1.Height / 2);
            //sprite1.Position = new Vector2(_random.Next(0,1000), _random.Next(0,1000));
            Monster.Instance.Monsters.Add(bm);
        }
        private static MonsterGenerator _instnace;
    }
}
